#ifndef TDACLIENTECORREO_H_
#define TDACLIENTECORREO_H_

/* Este TDA representa un cliente de correo operado por un usuario especifico que a su vez tiene una direccion de correo */
/* Salvo en la primitiva de creacion, se asume como PRE para todas las primitivas que el cliente de correo esta creado */
/* En todas las primitivas se asume en forma implicita que el primer parametro es una variable del tipo del TDA */

#include "TDACorreo.h"
#include "TDACanalSeguro.h"
#include "TDAServidorInseguro.h"
#include "vignere.h"


/* Tamano maximo de la clave de encriptacion */
#define MAX_KEY_LEN 32

/* Definicion del tipo de dato */
typedef struct {

	char direccion[MAX_ADDR_SIZE];
	int estadoConexion;
	char clave[MAX_CONTENT_LEN+1];
	TDAServidorInseguro *servidor;

} TDAClienteCorreo;

/*
 * Crea el cliente de correo
 *
 * Parametros:
 * direcUsr	un char* que apunta a una cadena de texto con la direccion de correo del usuario que opera el cliente de correo
 *
 * Valor de retorno:
 * N/A
 *
 * PRE: direcUsr apunta a una cadena de texto valida de no mas de MAX_ADDR_SIZE caracteres (segun define el TDACorreo)
 * POST: se ha creado el cliente de correo
 *
 */
void crearClienteCorreo(TDAClienteCorreo* clienteCorreo, char* direcUsr);

/*
 * Destruye el cliente de correo
 *
 * Parametros:
 * N/A
 *
 * Valor de retorno:
 * N/A
 *
 * PRE: N/A
 * POST: el cliente de correo se ha destruido (y cualquier conexion abierta se ha cerrado)
 *
 */
void destruirClienteCorreo(TDAClienteCorreo* clienteCorreo);

/*
 * Obtiene la direccion de correo del usuario que opera el cliente de correo
 *
 * Parametros:
 * direcUsr	un char* que apunta a un buffer donde se copiara la direccion de correo del usuario
 *
 * Valor de retorno:
 * N/A
 *
 * PRE: direcUsr apunta a una zona de memoria valida con espacio suficiente para contener MAX_ADDR_SIZE caracteres y ademas el caracter terminador de cadena
 * POST: se ha copiado en direcUsr la direccion de correo del usuario que opera el cliente de correo
 *
 */
void getDirecUsr(TDAClienteCorreo clienteCorreo, char* direcUsr);

/*
 * Envia la clave de encriptacion por el canal seguro
 *
 * Parametros:
 * canalSeguro	un canal seguro valido
 *
 * Valor de retorno:
 * N/A
 *
 * PRE: canalSeguro apunta a un canal seguro valido
 * POST: la clave de encriptacion se ha enviado por el canal seguro
 *
 */
void enviarClave(TDAClienteCorreo clienteCorreo, TDACanalSeguro* canalSeguro);

/*
 * Obtiene la clave de encriptacion del canal seguro
 *
 * Parametros:
 * canalSeguro	un canal seguro valido
 *
 * Valor de retorno:
 * N/A
 *
 * PRE: canalSeguro apunta a un canal seguro valido
 * 		no hay mensajes pendientes de ser obtenidos en el servidor dirigidos a este cliente de correo (los mensajes pendientes estan encriptados con la clave anterior)
 * POST: se ha obtenido la clave de encriptacion del canal seguro
 *
 */
void obtenerClave(TDAClienteCorreo* clienteCorreo, TDACanalSeguro canalSeguro);

/*
 * Regenera la clave de encriptacion
 *
 * Parametros:
 * N/A
 *
 * Valor de retorno:
 * N/A
 *
 * PRE: N/A
 * POST: la clave de encriptacion se ha regenerado
 *
 */
void regenerarClave(TDAClienteCorreo* clienteCorreo);

/*
 * Conecta el cliente de correo al servidor a traves de un canal inseguro
 *
 * Parametros:
 * servidorInseguro	un servidor valido, con el cual no se garantiza la seguridad en la comunicacion
 *
 * Valor de retorno:
 * 0 si fue posible conectarse al servidor
 * 1 si no fue posible conectarse al servidor
 *
 * PRE: servidorInseguro es un servidor valido
 * POST: se ha conectado el cliente de correo al servidor indicado
 *
 */
int conectar(TDAClienteCorreo* clienteCorreo, TDAServidorInseguro* servidorInseguro);

/*
 * Consulta si el cliente de correo esta conectado a un servidor
 *
 * Parametros:
 * N/A
 *
 * Valor de retorno:
 * 1 si el cliente de correo esta conectado a un servidor
 * 0 si el cliente de correo no esta conectado a servidor alguno
 *
 * PRE: N/A
 * POST: se ha devuelto un valor que indica si el cliente de correo esta conectado a un servidor o no
 *
 */
int estaConectado(TDAClienteCorreo clienteCorreo);

/*
 * Desconecta al cliente de correo del servidor
 *
 * Parametros:
 * N/A
 *
 * Valor de retorno:
 * N/A
 *
 * PRE: el cliente de correo esta conectado a un servidor
 * POST: el cliente de correo se ha desconectado del servidor
 *
 */
void desconectar(TDAClienteCorreo* clienteCorreo);

/*
 * Envia un correo al servidor
 *
 * Parametros:
 * correo	un correo valido a enviar
 *
 * Valor de retorno:
 * 0 si el correo fue enviado exitosamente
 * 1 si el correo no pudo ser enviado
 *
 * PRE: correo es un correo valido
 * POST: el correo se ha enviado al servidor
 *
 */
int enviarCorreo(TDAClienteCorreo clienteCorreo, TDACorreo correo);

/*
 * Recibe el proximo correo del servidor
 *
 * Parametros:
 * correo	un puntero a una zona de memoria valida con espacio suficiente para contener un correo
 *
 * Valor de retorno:
 * 0 si se ha podido recibir un nuevo correo
 * 1 si no habia mas correos para recibir
 * 2 si ocurrio un error al intentar recibir un nuevo correo
 *
 * PRE: correo apunta a una zona de memoria valida con especio suficiente para contener un correo
 * POST: se ha recibido un nuevo correo que puede obtenerse a partir del argumento correo provisto
 *
 */
int recibirProximoCorreo(TDAClienteCorreo clienteCorreo, TDACorreo* correo);

#endif /*TDACLIENTECORREO_H_*/
